package com.lbssoft.gpsbd.controller;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lbssoft.gpsbd.annotation.LogAnnotation;
import com.lbssoft.gpsbd.common.Constant;
import com.lbssoft.gpsbd.common.Hashing;
import com.lbssoft.gpsbd.common.LoggerUtil;
import com.lbssoft.gpsbd.common.Utils;
import com.lbssoft.gpsbd.dao.EventMapper;
import com.lbssoft.gpsbd.dao.UserMapper;
import com.lbssoft.gpsbd.model.LoginLog;
import com.lbssoft.gpsbd.model.Permission;
import com.lbssoft.gpsbd.model.Result;
import com.lbssoft.gpsbd.model.User;
import com.lbssoft.gpsbd.model.vo.LoginParam;
import com.lbssoft.gpsbd.model.vo.UserParam;
import com.lbssoft.gpsbd.model.vo.UserVo;
import com.lbssoft.gpsbd.service.LogService;
import com.lbssoft.gpsbd.service.PermissionService;
import com.lbssoft.gpsbd.service.UserService;
import com.mysql.jdbc.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.util.*;

@Api("用户管理")
@RestController
@RequestMapping(value="/users")
public class UserController {
	@Autowired
	UserMapper userMapper;

	@Autowired
	EventMapper eventMapper;

	@Autowired
	UserService userService;

	@Autowired
	PermissionService permissionService;

	@Autowired
	private LogService logService;

	@ApiOperation(value="注册用户", notes="注册用户")
	@ApiImplicitParams({
		@ApiImplicitParam(paramType="body",name = "param", value = "注册用户", required = true, dataType = "UserParam"),
	})
	@LogAnnotation(targetType = "user",action = "add",remark = "注册用户")
	@RequestMapping(value = "/register",method = {RequestMethod.POST})
	@ResponseBody
	public Result register(@Validated @RequestBody UserParam param) {
		return userService.regUser(param);
	}

	@ApiOperation(value="创建用户", notes="管理员创建用户")
	@ApiImplicitParams({
			@ApiImplicitParam(paramType="body",name = "param", value = "用户", required = true, dataType = "UserParam"),
	})
	@LogAnnotation(targetType = "user",action = "add",remark = "管理员创建用户")
	@RequiresPermissions("system:user:add")
	@RequestMapping(value = "",method = {RequestMethod.POST})
	@ResponseBody
	public Result add(@Validated @RequestBody UserParam param) {
		Result result = new Result();
		if(userMapper.getUserByAccount(param.getAccount())!=null){
			result.setCode(1);
			result.setMsg("用户名已经存在");
			return result;
		}
		User user = new User();
		user.setAccount(param.getAccount());
		Hashing.HashingResult hashingResult = Hashing.createHash(param.getPassword());
		user.setHashedPassword(hashingResult.hash);
		user.setSalt(hashingResult.salt);
		user.setEmail(param.getEmail());
		user.setPhone(param.getPhone());
		userMapper.addUser(user);
		for(Integer roleId:param.getRoleIds()){
			userService.addUserRole(roleId,user.getId());
		}

		return result;
	}
	
	
	@ApiOperation(value="用户登录", notes="用户登录")
	@ApiImplicitParams({
		@ApiImplicitParam(paramType="body",name = "login", value = "用户信息", required = true, dataType = "LoginParam"),
	})
	@LogAnnotation(targetType = "user",action = "login",remark = "用户登陆")
	@RequestMapping(value = "/login",method = {RequestMethod.POST})
	public Result login(@Validated @RequestBody LoginParam login, HttpServletRequest request){
		
		Result result = new Result();
		User u = userMapper.getUserByAccount(login.getAccount());
		if(u==null){
			result.setCode(1);
			result.setMsg("InvalidAccountNumber");

		}else if(u.isDisabled()) {
			result.setCode(1);
			result.setMsg("AccountIsDisabled");
		}else{
			String hashedPassword= u.getHashedPassword();
			String salt= u.getSalt();
			boolean  isLogin = Hashing.validatePassword(login.getPassword(), hashedPassword, salt);
			if(!isLogin){
				result.setCode(1);
				result.setMsg("IncorrectPassword");
				return result;
			}
			String token = Utils.getUUID();
			Map userToken = userService.getUserById(u.getId());
			//登陆前清理token
			if(userToken.get("token")!=null&&!Constant.ALLOW_MULTIPLE_TERMINALS){
				userService.cleanToken(userToken.get("token").toString(),u.getId());
			}
			userMapper.udpateToken(token, u.getId());
			Map<String,Object> userMap = new HashMap<String, Object>();
			userMap.put("id",u.getId());
			userMap.put("account", u.getAccount());
			userMap.put("token", token);
			result.setCode(0);
			result.setData(userMap);
			//插入登录日志
			LoginLog log = new LoginLog();
			log.setUserId(u.getId());
			log.setClient(login.getClient());
			log.setIp(LoggerUtil.getCliectIp(request));
			logService.addLoginLog(log);
		}
		
		return result;
	}

	@ApiOperation(value="用户信息", notes="用户信息")
	@RequestMapping(value = "",method = {RequestMethod.GET})
	public Result info(){
		UserVo user = (UserVo)SecurityUtils.getSubject().getPrincipal();
		Result result = new Result();
		HashMap data = new HashMap();
		HashMap messages = new HashMap();
		messages.put("unReadEventCount",eventMapper.getUnReadCount(user.getId()));
		data.put("messages",messages);
		data.put("user",userMapper.getUserById(user.getId()));
		result.setCode(0);
		result.setMsg("用户信息");
		result.setData(data);
		return result;
	}

	@ApiOperation(value="修改密码", notes="修改密码")
	@ApiImplicitParams({
			@ApiImplicitParam(paramType="body",name = "param", value = "用户密码", required = true, dataType = "Map"),
	})
	@LogAnnotation(targetType = "user",action = "update",remark = "修改密码")
	@RequiresPermissions(value = {"user:user:update", "system:user:update"}, logical = Logical.OR)
	@RequestMapping(value = "/updatepass",method = {RequestMethod.PUT})
	@ResponseBody
	public Result updatePassword(@Validated @RequestBody Map param) {
		UserVo user = (UserVo)SecurityUtils.getSubject().getPrincipal();
		Result result = new Result();
		if(!param.get("password").equals(param.get("password2"))){
			result.setCode(1);
			result.setMsg("PasswordIsInconsistent");
			return result;
		}
		Hashing.HashingResult hashingResult = Hashing.createHash(param.get("password").toString());
		userMapper.updatePassword(user.getId(),hashingResult.hash, hashingResult.salt);
		return result;
	}

	@ApiOperation(value="用户角色权限", notes="用户角色权限")
	@RequestMapping(value = "permissions",method = {RequestMethod.GET})
	public Result permissions(){
		UserVo user = (UserVo)SecurityUtils.getSubject().getPrincipal();
		Result result = new Result();
		Map map = new HashMap();
		Set<String> permissionList = new HashSet();
		//Set<String> menuList = new HashSet();
		String[] roleIds = user.getRoleIds().split(",");
		List<Permission> permissions  = new ArrayList<>();
		for(String roleId:roleIds){
			permissions.addAll(permissionService.getPermissionsByRoleId(Integer.parseInt(roleId)));

		}
		//todo 需要优化 如果是多角色需要获取多个角色菜单权限去重复
		//如果是管理员组
		if(user.getGroupId()==1){
			map.put("routers",permissionService.getMenusByRoleId(Integer.parseInt(roleIds[0]),1));
		}


		for(Permission permis:permissions){
			if(permis!=null&&permis.getType()!=0){
				permissionList.add(permis.getPermis());
			}
//			if(permis!=null&&(permis.getType()==0||permis.getType()==1)){{
//				menuList.add(permis.getPermis());
//			}
//
//			}

		}
		result.setCode(0);

		//map.put("groupId",user.getGroupId());
		//map.put("role",user.getRoleKey());
		map.put("permissions",permissionList);
	//	map.put("menus",menuList);
		Map u = new HashMap();
		u.put("account",user.getAccount());
		u.put("roleKeys",user.getRoleKeys());
		u.put("groupId",user.getGroupId());
		map.put("user",u);
		result.setMsg("用户权限资源");
		result.setData(map);
		return result;
	}

	@ApiOperation(value="获取用户列表", notes="获取用户列表")
	@RequiresPermissions("system:user:view")
	@RequestMapping(value = "/list",method = {RequestMethod.GET})
	public Result list(@NotEmpty @RequestParam(value = "page", defaultValue = "1") int page,
					   @NotEmpty @RequestParam(value = "pageSize", defaultValue = "10") int pageSize,
					   @RequestParam(value = "column", defaultValue = "") String column,
					   @RequestParam(value = "keyword", defaultValue = "") String keyword,
					   @RequestParam(value = "status") Integer status){
		String where = " where 1=1 ";
		if(!StringUtils.isNullOrEmpty(column)&&!StringUtils.isNullOrEmpty(keyword)){
			where = where+" and "+column+" LIKE '%"+keyword+"%'";
		}
		if(status!=-1){
			where = where+" and status="+status;
		}
		PageHelper.startPage(page, pageSize);
		List<UserVo> list = userService.getUsers(where);
		PageInfo pageInfo = new PageInfo(list);
		Page pages = (Page) list;
		Result result = new Result();
		Map data = new HashMap();
		data.put("page", page);
		data.put("total", pageInfo.getTotal());
		data.put("list", pages);
		result.setData(data);
		return result;
	}

	@ApiOperation(value="删除用户", notes="删除用户")
	@RequiresPermissions("system:user:delete")
	@LogAnnotation(targetType = "user",action = "delete",remark = "删除用户")
	@RequestMapping(value = "/{id}",method = {RequestMethod.DELETE})
	@ResponseBody
	public Result delete(@NotNull @PathVariable long id) {
		return userService.delete(id);
	}

	@ApiOperation(value="修改用户信息", notes="修改用户信息")
	@ApiImplicitParams({
			@ApiImplicitParam(paramType="body",name = "param", value = "用户密码", required = true, dataType = "UserParam"),
	})
	@RequiresPermissions("system:user:update")
	@LogAnnotation(targetType = "user",action = "update",remark = "修改用户信息")
	@RequestMapping(value = "",method = {RequestMethod.PUT})
	@ResponseBody
	public Result update(@Validated @RequestBody UserParam param) {
		Result result = new Result();
		Map user = userService.getUserById(param.getId());
		if(user.get("account").equals("root")){
			result.setCode(1);
			result.setMsg("默认超级管理员不可修改");
			return result;
		}
		//修改用户信息清理token
		if(user.get("token")!=null){
			userService.cleanToken(user.get("token").toString(),param.getId());
		}
		userService.update(param);
		userService.deleteUserRole(param.getId());
		for(Integer roleId:param.getRoleIds()){
			userService.addUserRole(roleId,param.getId());
		}
		return result;
	}

	@ApiOperation(value="退出登录", notes="退出登录")
	@LogAnnotation(targetType = "user",action = "get",remark = "退出登陆")
	@RequestMapping(value = "/exit",method = {RequestMethod.GET})
	@ResponseBody
	public Result exit() {
		UserVo user = (UserVo)SecurityUtils.getSubject().getPrincipal();
		Result result = new Result();
		Map userMap = userService.getUserById(user.getId());
		if(userMap.get("token")!=null){
			userService.cleanToken(userMap.get("token").toString(),user.getId());
		}
		return result;
	}

	@ApiOperation(value="生成监控token", notes="生成监控token")
	@RequiresRoles(value={"root","administrators"},logical = Logical.OR)
	@LogAnnotation(targetType = "user",action = "update",remark = "监控用户")
	@RequestMapping(value = "/token/{userId}",method = {RequestMethod.PUT})
	@ResponseBody
	public Result generateToken(@NotNull @PathVariable long userId) {
		Result result = new Result();
		Map userMap = userService.getUserById(userId);
		if(userMap.get("token")==null){
			String token = Utils.getUUID();
			userMapper.udpateToken(token, userId);
			result.setData(token);
		}else {
			result.setData(userMap.get("token"));
		}

		return result;
	}

}